package org.koin.experimental.builder;

import org.koin.core.definition.BeanDefinition;
import org.koin.core.definition.Definition;
import org.koin.core.error.DefinitionOverrideException;
import org.koin.core.module.Module;
import org.koin.core.parameter.DefinitionParameters;
import org.koin.core.qualifier.Qualifier;
import org.koin.core.scope.Scope;

public class ModuleExt {

    /**
     * Create a Single definition for given type T
     *
     * @param qualifier
     * @param createOnStart - need to be created at start
     * @param override      - allow definition override
     */
    public static <T> BeanDefinition<T> single(
            Class<T> tClass,
            Module module,
            Qualifier qualifier,
            boolean createOnStart,
            boolean override
    ) throws DefinitionOverrideException {

        return module.single(tClass, qualifier, createOnStart, override, new Definition<T>() {
            @Override
            public T invoke(Scope scope, DefinitionParameters parameters) {
                try {
                    return InstanceBuilder.create(scope, tClass);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        });
    }

    /**
     * Create a Factory definition for given type T
     *
     * @param qualifier
     * @param override  - allow definition override
     */
    public static <T> BeanDefinition<T> factory(
            Module module,
            Class<T> tClass,
            Qualifier qualifier,
            boolean override
    ) throws DefinitionOverrideException {
        return module.factory(tClass, qualifier, override, new Definition<T>() {
            @Override
            public T invoke(Scope scope, DefinitionParameters parameters) {
                try {
                    return InstanceBuilder.create(scope, tClass);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        });
    }

    public static <R, T extends R> BeanDefinition<R> singleBy(
            Module module,
            Class<R> rClass,
            Class<T> tClass,
            Qualifier qualifier,
            boolean createOnStart,
            boolean override
    ) throws DefinitionOverrideException {
        return module.single(rClass, qualifier, createOnStart, override, new Definition<R>() {
            @Override
            public R invoke(Scope scope, DefinitionParameters parameters) {
                try {
                    return InstanceBuilder.create(scope, tClass);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        });
    }

    public static <R, T extends R> BeanDefinition<R> singleBy(
            Module module,
            Class<R> rClass,
            Class<T> tClass
    ) throws DefinitionOverrideException {
        return singleBy(module, rClass, tClass, null, false, false);
    }

    public static <R, T extends R> BeanDefinition<R> factoryBy(
            Module module,
            Class<R> rClass,
            Class<T> tClass,
            Qualifier qualifier,
            boolean override
            ) throws DefinitionOverrideException {

        return module.factory(rClass, qualifier, override, new Definition<R>() {
            @Override
            public R invoke(Scope scope, DefinitionParameters parameters) {
                try {
                    return InstanceBuilder.create(scope, tClass);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            }
        });
    }

}
